home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 201-225 / disk_219 / mv / mv.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  39KB  |  1,880 lines

  1. /*
  2.  * mv v1.0 - Unix-like move file utility
  3.  *
  4.  * Copyright 1989 Edwin Hoogerbeets
  5.  *
  6.  * This code may be freely redistributed as long as no charges other than
  7.  * reasonable copying fees are levied for it.
  8.  *
  9.  * Manx version by Edwin Hoogerbeets
  10.  * usenet: edwin@watcsc.waterloo.edu
  11.  * CIS:    72647,3675
  12.  *
  13.  * Works mostly like the Unix move.
  14.  *
  15.  * Usage: mv [-cfix]    [-] file1 file2
  16.  *        mv [-cfix]    [-] path1 [path2 ...] dir
  17.  *        cp [-fimnx]   [-] file1 file2
  18.  *        cp [-fimnxrR] [-] path1 [path2 ...] dir
  19.  *        rm [-cdfimrR] [-] path  [path ...]
  20.  *
  21.  * Where path is either a file or a directory.
  22.  *
  23.  *  -c act like cp instead (as in "mv -c" means do a cp instead of mv)
  24.  *  -d remove directories only if they are empty (as in AmigaDOS Delete)
  25.  *  -f force quiet mode, overwriting destination files if necessary.
  26.  *  -i force interactive mode
  27.  *  -m act like mv instead
  28.  *  -n do not copy file dates, comments and protections (use "n"ew dates..)
  29.  *  -R same as -r
  30.  *  -r recursively do directories as well (mv is always recursive)
  31.  *  -x act like rm instead
  32.  *  -  end of options (useful to remove a file whose name starts with
  33.  *     a dash eg. "-d")
  34.  *
  35.  * Moves, etc. across devices are supported.
  36.  *
  37.  */
  38.  
  39. #include <fcntl.h>
  40. #include <libraries/dos.h>
  41. #include <libraries/dosextens.h>
  42. #ifdef ARP
  43. #include <libraries/arpbase.h>
  44. #include <libraries/arpfunc.h>
  45. #endif
  46. #include <exec/memory.h>
  47. #include <ctype.h>
  48.  
  49. #define FIBSIZE (long)sizeof(struct FileInfoBlock)
  50. #define BUFSIZE 256
  51.  
  52. typedef struct fl {
  53.   char name[BUFSIZE];
  54.   struct fl *next;
  55. } filenode;
  56.  
  57. #define FNSIZE (long)sizeof(filenode)
  58.  
  59. struct FileLock          *lock;
  60. struct FileInfoBlock     *fib;
  61.  
  62. int mvflag = 0, /* is this a move command? */
  63.     cpflag = 0, /* is this a copy command? */
  64.     rmflag = 0, /* is this a remove command? */
  65.     rflag  = 0, /* is this command recursive? */
  66.     fflag  = 0, /* don't ask if it should overwrite, just do it */
  67.     iflag  = 0, /* do interactive mode */
  68.     nflag  = 1, /* copy file dates, comments and protections */
  69.     dflag  = 0; /* delete directories only if they are empty */
  70.  
  71. char commandname[32] = "";
  72.  
  73. long ofile;     /* output file handle */
  74. long ifile;     /* input file handle  */
  75.  
  76. #ifdef ARP
  77.  
  78. typedef struct BAP {
  79.   struct AnchorPath bap_ap;
  80.   char padding[BUFSIZE];
  81. } BigAnchorPath;
  82.  
  83. #define APSIZE (long)sizeof(BigAnchorPath)
  84.  
  85. int arpflag = 0;
  86.  
  87. #endif
  88.  
  89. /* these are so Manx won't complain about ptr/int conversions, etc. */
  90. extern struct FileLock   *ParentDir();
  91. extern struct FileLock   *CreateDir();
  92. extern struct FileLock   *Lock();
  93. extern struct FileLock   *CurrentDir();
  94. extern int                Examine();
  95. extern char              *AllocMem();
  96. extern struct FileHandle *Open();
  97. extern struct MsgPort    *DeviceProc();
  98. extern struct Library    *OpenLibrary();
  99. extern struct _dev       *_devtab;
  100.  
  101. #ifdef ARP
  102. struct ArpBase       *ArpBase;
  103. struct IntuitionBase *IntuitionBase;
  104. struct GfxBase       *GfxBase;
  105. #endif
  106.  
  107. #include <exec/alerts.h>
  108. #include <workbench/startup.h>
  109.  
  110. extern long _savsp, _stkbase;
  111.  
  112. extern int errno;
  113. extern int Enable_Abort;
  114.  
  115. extern int _argc, _arg_len;
  116. extern char **_argv, *_arg_lin;
  117.  
  118. _main(alen, aptr)
  119. long alen;
  120. char *aptr;
  121. {
  122.         struct Process *pp, *FindTask();
  123.  
  124.         _stkbase = _savsp - *((long *)_savsp+1) + 8;
  125.         *(long *)_stkbase = 0x4d414e58L;
  126.  
  127.         pp = FindTask(0L);
  128.         _cli_parse(pp, alen, aptr);
  129.         Enable_Abort = 1;
  130.  
  131.         exit(main(_argc, _argv));
  132. }
  133.  
  134. /*
  135.  * The following few routines were taken from my edlib1.1 source. They
  136.  * are included here so that anyone can recompile this source without
  137.  * the library. (I'll be happy to send you edlib if you want it.)
  138.  */
  139.  
  140. char *strrpbrk(str, charset)
  141. register char *str, *charset;
  142. {
  143.   register char *temp;
  144.   extern char *index();
  145.  
  146.   temp = str + strlen(str) - 1;
  147.  
  148.   while ( temp != (str - 1)  && !index(charset, *temp) )
  149.     --temp;
  150.  
  151.   return( (temp != (str - 1)) ? temp : NULL);
  152. }
  153.  
  154. int stricmp(str1,str2)
  155. register char *str1,*str2;
  156. {
  157.     register int index = 0;
  158.  
  159.     while ( str1[index] && str2[index] &&
  160.             tolower(str1[index]) == tolower(str2[index]) )
  161.         ++index;
  162.  
  163.     return( (tolower(str1[index]) < tolower(str2[index])) ? -1 :
  164.           ( (tolower(str1[index]) > tolower(str2[index])) ?  1 : 0) );
  165. }
  166.  
  167.  
  168. /* return a pointer to the first character of a file name in a path name */
  169. char *basename(buf)
  170. register char *buf;
  171. {
  172.   register char *foo = strrpbrk(buf,":/");
  173.  
  174.   return( foo ? (foo + 1) : buf );
  175. }
  176.  
  177. /* end of edlib routines */
  178.  
  179. /* write out a string */
  180. int emit(file,str)
  181. long file;
  182. char *str;
  183. {
  184.   Write(file,str,strlen(str));
  185. }
  186.  
  187. /*
  188.  * return the length of the largest piece of memory that is possibly
  189.  * contiguous
  190.  */
  191. long mem()
  192. {
  193.    long chip, fast;
  194.    extern long AvailMem();
  195.  
  196.    Forbid();
  197.    chip = AvailMem(MEMF_CHIP);
  198.    fast = AvailMem(MEMF_FAST);
  199.    Permit();
  200.  
  201.    return(chip>fast ? chip : fast);
  202. }
  203.  
  204. /* make a new file info block and return a pointer to it */
  205. struct FileInfoBlock *newfib()
  206. {
  207.   struct FileInfoBlock *fib;
  208.  
  209.   fib = (struct FileInfoBlock *) AllocMem(FIBSIZE, MEMF_CLEAR);
  210.  
  211.   if ( !fib ) {
  212.     if ( !fflag ) {
  213.       emit(ofile,commandname);
  214.       emit(ofile,": Out of memory!\n");
  215.     }
  216.     return(NULL);
  217.   }
  218.  
  219.   return(fib);
  220. }
  221.  
  222. /* get rid of a used file info block */
  223. int freefib(fib)
  224. {
  225.   if ( fib )
  226.     FreeMem(fib,FIBSIZE);
  227. }
  228.  
  229. /* make a new buffer and return a pointer to it */
  230. char *newbuf()
  231. {
  232.   register char *temp = AllocMem(BUFSIZE,MEMF_CLEAR|MEMF_PUBLIC);
  233.  
  234.   if ( !temp ) {
  235.     if ( !fflag ) {
  236.       emit(ofile,commandname);
  237.       emit(ofile,": Out of memory!\n");
  238.     }
  239.     return(NULL);
  240.   }
  241.  
  242.   return(temp);
  243. }
  244.  
  245. /* free a buffer previously allocated with newbuf() */
  246. int freebuf(buf)
  247. char *buf;
  248. {
  249.   if ( buf ) {
  250.     FreeMem(buf,BUFSIZE);
  251.   }
  252. }
  253.  
  254. /* make a new filenode structure and return a pointer to it */
  255. filenode *newfilenode()
  256. {
  257.   filenode *new = (filenode *)
  258.     AllocMem(FNSIZE,MEMF_PUBLIC|MEMF_CLEAR);
  259.  
  260.   if ( new ) {
  261.     new->name[0] = '\0';
  262.     new->next = NULL;
  263.   }
  264.  
  265.   return(new);
  266. }
  267.  
  268. /* free a list of filenode structures */
  269. int freefilenodes(file)
  270. filenode *file;
  271. {
  272.   if ( file ) {
  273.     freefilenodes(file->next);
  274.  
  275.     FreeMem(file,FNSIZE);
  276.   }
  277. }
  278.  
  279. /* return a pointer to the last element of a filenode list */
  280. filenode *end(file)
  281. filenode *file;
  282. {
  283.   if ( file ) {
  284.     if ( file->next ) {
  285.       return(end(file->next));
  286.     } else {
  287.       return(file);
  288.     }
  289.   } else {
  290.     return(NULL);
  291.   }
  292. }
  293.  
  294. /* return the length of a list of filenodes */
  295. int arglength(file)
  296. filenode *file;
  297. {
  298.   if ( file->next ) {
  299.     return(arglength(file->next)+1);
  300.   } else {
  301.     return(1);
  302.   }
  303. }
  304.  
  305. /* Does the input string contain a wildcard? */
  306. int haswild(name)
  307. char *name;
  308. {
  309.   register int foo = 0;
  310.  
  311.   while ( name[foo] && name[foo] != '*' && name[foo] != '?' &&
  312.           name[foo] != '#' )
  313.     ++foo;
  314.  
  315.   return ( name[foo] );
  316. }
  317.  
  318.  
  319. /*
  320.  * This routine takes a string with possibly a wildcard in it and expands
  321.  * it to a list of filenode structures. If arp isn't opened or if it
  322.  * wasn't compiled with arp, then it creates a list of 1 filenode containing
  323.  * the argument it was passed. The pointer to nomem is where it puts the
  324.  * error code for "low on available memory" errors.
  325.  */
  326. filenode *expand(name,nomem)
  327. char *name;
  328. int *nomem;
  329. {
  330.   filenode *file;
  331.  
  332. # ifdef ARP
  333.   if ( arpflag && haswild(name) ) {
  334.     filenode *temp;
  335.     int error;
  336.     BigAnchorPath *anchor;
  337.  
  338.     *nomem = 0;
  339.  
  340.     anchor = (BigAnchorPath *)
  341.         AllocMem(APSIZE,MEMF_CLEAR|MEMF_PUBLIC);
  342.  
  343.     anchor->bap_ap.ap_Length = BUFSIZE;
  344.  
  345.     if ( FindFirst(name,anchor) ) {
  346.       FreeAnchorChain(anchor);
  347.       return(NULL);
  348.     }
  349.  
  350.     if ( file = newfilenode() ) {
  351.       strcat(file->name,anchor->bap_ap.ap_Buf);
  352.     } else {
  353.       *nomem = 1;
  354.       FreeAnchorChain(anchor);
  355.       return(NULL);
  356.     }
  357. #   ifdef DEBUG
  358.     printf("First matched file: %s\n",file->name);
  359. #   endif
  360.  
  361.     temp = file;
  362.  
  363.     while ( !(error = FindNext(anchor)) ) {
  364.  
  365.       if ( !(temp->next = newfilenode()) ) {
  366.         *nomem = 1;
  367.         FreeAnchorChain(anchor);
  368.         freefilenodes(file);
  369.         return(NULL);
  370.       }
  371.  
  372.       temp = temp->next;
  373.  
  374.       strcat(temp->name,anchor->bap_ap.ap_Buf);
  375.  
  376. #   ifdef DEBUG
  377.     printf("Next matched file: %s\n",temp->name);
  378. #   endif
  379.     }
  380.  
  381.     FreeAnchorChain(anchor);
  382.   } else {
  383. # endif
  384.     file = newfilenode();
  385.  
  386.     if ( file ) {
  387.       *nomem = 0;
  388.       strcat(file->name,name);
  389.     } else {
  390.       *nomem = 1;
  391.       return(NULL);
  392.     }
  393.  
  394. # ifdef ARP
  395.   }
  396. # endif
  397.  
  398.   return(file);
  399. }
  400.  
  401. /* well, I guess this is a pro-choice program. ;-) */
  402. _abort()
  403. {
  404.   if ( lock )
  405.     UnLock(lock);
  406.  
  407.   exit(-1);
  408. }
  409.  
  410. /*
  411.  * make a string containing the path part of a full AmigaDOS path name.
  412.  * return a pointer to this string.
  413.  */
  414. char *parent(name)
  415. char *name;
  416. {
  417.   register char *foo;
  418.   char *temp = AllocMem((long)strlen(name)+1,MEMF_CLEAR);
  419.  
  420.   strcat(temp,name);
  421.  
  422.   /* get a pointer to the filename part */
  423.   foo = basename(temp);
  424.  
  425.   /*
  426.    * lop off the file name part -- the length of the whole original
  427.    * string must still be freed when freeing what temp points to.
  428.    */
  429.   *foo = '\0';
  430.  
  431.   return(temp);
  432. }
  433.  
  434. /* are the two files on the same volume? If you can't tell, guess */
  435. int samedev(src,dst)
  436. char *src, *dst;
  437. {
  438.   char  srcbuf[40], dstbuf[40], *temp;
  439.   struct FileLock *lock;
  440.  
  441.   /* Simultaneous get a lock and convert BPTR to a C pointer */
  442.   lock = (struct FileLock *)BADDR(Lock(src,ACCESS_READ));
  443.  
  444.   if (lock == NULL) {
  445.     return(-1);
  446.   }
  447.  
  448.   temp = (char *)
  449.     BADDR(((struct DeviceList *)BADDR(lock->fl_Volume))->dl_Name);
  450.  
  451.   strncpy(srcbuf,&temp[1],temp[0]+1);
  452.   srcbuf[temp[0]+2] = '\0';
  453.  
  454.   UnLock(((long)lock) >> 2);  /* You must UnLock or the GURU visits */
  455.  
  456.   temp = parent(dst);
  457.  
  458.   lock = (struct FileLock *)BADDR(Lock(temp,ACCESS_READ));
  459.  
  460.   FreeMem(temp,strlen(dst)+1);
  461.  
  462.   if (lock == NULL) {
  463.     return(-1);
  464.   }
  465.  
  466.   temp = (char *)
  467.     BADDR(((struct DeviceList *)BADDR(lock->fl_Volume))->dl_Name);
  468.  
  469.   strncpy(dstbuf,&temp[1],temp[0]+1);
  470.   dstbuf[temp[0]+2] = '\0';
  471.  
  472.   UnLock(((long)lock) >> 2);  /* You must UnLock or the GURU visits */
  473.  
  474. # ifdef DEBUG
  475.   printf("%s and %s are %son the same volume\n",src,dst,
  476.         (!stricmp(srcbuf,dstbuf))?"":"not ");
  477. # endif
  478.   return( !stricmp(srcbuf,dstbuf) );
  479. }
  480.  
  481. /*
  482.  * Is the named file a directory? Get a File Info Block and point fib to
  483.  * it and return the results.
  484.  *
  485.  * return   0  for not a dir (ie. file)
  486.  * return   1  for a dir
  487.  * return   2  for no access to file
  488.  * return   3  for not being able to examine file
  489.  *
  490.  */
  491. int isdir(path,fib)
  492. char *path;
  493. struct FileInfoBlock **fib;
  494. {
  495.   struct FileLock *lock;
  496.   register int result;
  497.  
  498.   /* allocate a word aligned memory block to hold our info */
  499.   *fib = newfib();
  500.  
  501.   if ( !(lock = Lock(path,ACCESS_READ)) ) {
  502.     return(2);
  503.   }
  504.  
  505.   if ( *fib ) {
  506.     if ( Examine(lock,*fib) ) {
  507.  
  508.       /* if the source is not a directory .. */
  509.       result = (*fib)->fib_DirEntryType > 0 ? 1 : 0;
  510.  
  511.     } else {
  512.       /* 3 for could not examine */
  513.       result = 3;
  514.     }
  515.  
  516.   } else {
  517.     if ( !fflag ) {
  518.       emit(ofile,commandname);
  519.       emit(ofile,": Out of memory!\n");
  520.     }
  521.     UnLock(lock);
  522.     return(-1);
  523.   }
  524.  
  525.   UnLock(lock);
  526.  
  527.   return(result);
  528. }
  529.  
  530. #ifdef ARP
  531. void closethings()
  532. {
  533.   if ( ArpBase ) {
  534.     CloseLibrary(ArpBase);
  535.   }
  536.  
  537.   if ( IntuitionBase ) {
  538.     CloseLibrary(IntuitionBase);
  539.   }
  540.  
  541.   if ( GfxBase ) {
  542.     CloseLibrary(GfxBase);
  543.   }
  544.  
  545. }
  546. #endif
  547.  
  548. void usage()
  549. {
  550.   if ( !fflag ) {
  551.     emit(ofile,"Usage: mv [-cfix]    [-] file1 file2\n");
  552.     emit(ofile,"       mv [-cfix]    [-] path1 [path2 ...] dir\n");
  553.     emit(ofile,"       cp [-fimnx]   [-] file1 file2\n");
  554.     emit(ofile,"       cp [-fimnxrR] [-] path1 [path2 ...] dir\n");
  555.     emit(ofile,"       rm [-cdfimrR] [-] path  [path ...]\n");
  556.     emit(ofile,"\nWhere path is either a file or a directory.\n");
  557.   }
  558.  
  559. # ifdef ARP
  560.   closethings();
  561. # endif
  562.  
  563.   exit(1);
  564. }
  565.  
  566. /* the following is a mess. brace yourself. */
  567. main(argc,argv)
  568. int argc;
  569. char *argv[];
  570. {
  571.   register int index, c;
  572.   struct FileInfoBlock *startfib = NULL, *endfib = NULL;
  573.   filenode *start = NULL, *temp = NULL, *endnode = NULL;
  574.   int args, result, nomem;
  575.  
  576.   ofile = (long) Open("*",MODE_NEWFILE); /* open new file for stderr */
  577.   ifile = Input();
  578.  
  579. # ifdef ARP
  580.   ArpBase = (struct ArpBase *) OpenLibrary(ArpName,0L);
  581.  
  582.   if ( ArpBase ) {
  583. #   ifdef DEBUG
  584.     printf("opened arp.library okay\n");
  585. #   endif
  586.  
  587.     if ( !(IntuitionBase = (struct IntuitionBase *)
  588.            OpenLibrary("intuition.library",0L)) ) {
  589.       emit(ofile,"Could not open intuition.library\n");
  590. #     ifdef ARP
  591.       closethings();
  592. #     endif
  593.       exit(-1);
  594.     }
  595.  
  596.     if ( !(GfxBase = (struct GfxBase *)
  597.            OpenLibrary("graphics.library",0L)) ) {
  598.       emit(ofile,"Could not open graphics.library\n");
  599. #     ifdef ARP
  600.       closethings();
  601. #     endif
  602.       exit(-1);
  603.     }
  604.     arpflag = 1;
  605.   } else {
  606. #   ifdef DEBUG
  607.     printf("Arp.library not opened.\n");
  608. #   endif
  609.     arpflag = 0;
  610.   }
  611. # endif
  612.  
  613.   if ( !stricmp(basename(argv[0]),MVNAME) ) {
  614.  
  615.     ++mvflag;
  616.     ++rflag;
  617.  
  618.   } else if ( !stricmp(basename(argv[0]),RMNAME) ) {
  619.  
  620.     ++rmflag;
  621.  
  622.   } else {
  623.  
  624.     /*
  625.      * default to the copy command so that if the user renames the
  626.      * executable to something we don't understand, we don't do
  627.      * anything really destructive.
  628.      */
  629.     ++cpflag;
  630.   }
  631.  
  632.   index = 1;
  633.  
  634.   /* simplistic argument processing */
  635.  
  636.   while ( argv[index][0] == '-' ) {
  637.     c = 1;
  638.  
  639.     /* - option was specified to end other options */
  640.     if ( !argv[index][c] ) {
  641.       ++index;
  642.       break;
  643.     }
  644.  
  645.     while ( argv[index][c] ) {
  646.       switch ( argv[index][c] ) {
  647.         case 'c':
  648.           cpflag = 1;
  649.           rflag = mvflag = rmflag = 0;
  650.           break;
  651.  
  652.         case 'd':
  653.           dflag = 1;
  654.           break;
  655.  
  656.         case 'f':
  657.           fflag = 1;
  658.           iflag = 0;
  659.           break;
  660.  
  661.         case 'i':
  662.           fflag = 0;
  663.           iflag = 1;
  664.           break;
  665.  
  666.         case 'm':
  667.           rflag = mvflag = 1;
  668.           cpflag = rmflag = 0;
  669.           break;
  670.  
  671.         case 'n':
  672.           nflag = 0;
  673.           break;
  674.  
  675.         case 'R':
  676.         case 'r':
  677.           rflag = 1;
  678.           break;
  679.  
  680.         case 'x':
  681.           rmflag = 1;
  682.           rflag = mvflag = cpflag = 0;
  683.           break;
  684.  
  685.         default:
  686.           emit(ofile,"invalid option ");
  687.           Write(ofile,&argv[index][c],1);
  688.           emit(ofile,"\n");
  689.           usage();
  690.       }
  691.       c++;
  692.     }
  693.     ++index;
  694.   }
  695.  
  696.   /* if there are no file names left after the options were processed ... */
  697.   if ( (argc - index) < (rmflag ? 1 : 2) ) {
  698.     usage();
  699.   }
  700.  
  701.   if ( mvflag ) {
  702.  
  703.     strcat(commandname,MVNAME);
  704. #   ifdef DEBUG
  705.     printf("mv command executing\n");
  706. #   endif
  707.  
  708.   } else if ( rmflag ) {
  709.  
  710.     strcat(commandname,RMNAME);
  711. #   ifdef DEBUG
  712.     printf("rm command executing\n");
  713. #   endif
  714.  
  715.   } else {
  716.  
  717.     strcat(commandname,CPNAME);
  718. #   ifdef DEBUG
  719.     printf("cp command executing\n");
  720. #   endif
  721.  
  722.   }
  723.  
  724.   /*
  725.    * expand the first argument. index contains the number of the first
  726.    * file name argument at this point, because it is updated by the options
  727.    * parsing piece of code above.
  728.    */
  729.   start = expand(argv[index++],&nomem);
  730.  
  731.   if ( nomem ) {
  732.     if ( !fflag ) {
  733.       emit(ofile,commandname);
  734.       emit(ofile,": Out of memory!\n");
  735.     }
  736. #   ifdef ARP
  737.     closethings();
  738. #   endif
  739.     exit(-1);
  740.   }
  741.  
  742.   temp = end(start);
  743.  
  744.   for ( ;index < argc; index++) {
  745.  
  746.     /*
  747.      * it is possible that previous arguments had a wildcard and didn't
  748.      * match anything, so temp would be NULL at this point, otherwise
  749.      * attach the new file list from expand onto the end of the list.
  750.      */
  751.     if ( temp ) {
  752.       temp->next = expand(argv[index],&nomem);
  753.     } else {
  754.       temp = expand(argv[index],&nomem);
  755.       start = temp;
  756.     }
  757.  
  758.     if ( nomem ) {
  759.       if ( !fflag ) {
  760.         emit(ofile,commandname);
  761.         emit(ofile,": Out of memory!\n");
  762.       }
  763. #     ifdef ARP
  764.       closethings();
  765. #     endif
  766.       freefilenodes(start);
  767.       exit(-1);
  768.     }
  769.  
  770.     temp = end(temp);
  771.   }
  772.  
  773.   endnode = end(start);
  774.   args = arglength(start);
  775.  
  776. # ifdef DEBUG
  777.   printf("argc: %d\n",argc);
  778.  
  779.   for ( temp = start; temp; temp = temp->next ) {
  780.     printf("argument \"%s\"\n", temp->name );
  781.   }
  782. # endif
  783.  
  784.   if ( !rmflag ) {
  785.  
  786.     /*
  787.      * main case statement for the program to find out what to do with
  788.      * its life. (You gotta fight, for your right,
  789.      * to PPPPPAAAAAAARRRRRRRRIIIIIIIITTTTTTTYYYYYY!!!!!!
  790.      */
  791.  
  792.     /*
  793.      * check last argument (ie. the destination file) to make sure it
  794.      * is a directory
  795.      */
  796.     switch ( isdir(endnode->name,&endfib) ) {
  797.  
  798.       /*
  799.        * destination is a file, check that there are only 2 arguments
  800.        * and that the first one is also a file, or inform the user
  801.        * of his (or her) silliness.
  802.        */
  803.       case 0:
  804.         if ( args == 2 ) {
  805.           if ( isdir(start->name,&startfib) ) {
  806.             if ( !fflag ) {
  807.               emit(ofile,commandname);
  808.               emit(ofile,": cannot move a directory onto a file\n");
  809.             }
  810.  
  811.             freefib(startfib);
  812.             freefib(endfib);
  813.             freefilenodes(start);
  814.             usage();
  815.  
  816.           } else {
  817.  
  818.             result = mv2f(start->name,startfib,endnode->name,endfib);
  819.  
  820.             if ( result == 2 && mvflag ) {
  821.               rm(start->name,fflag,iflag);
  822.             }
  823.  
  824.             freefib(startfib);
  825.             freefib(endfib);
  826.             freefilenodes(start);
  827.             exit(0);
  828.           }
  829.         } else {
  830.           if ( !fflag ) {
  831.             emit(ofile,commandname);
  832.             emit(ofile,": cannot move a directory onto a file\n");
  833.           }
  834.           freefib(endfib);
  835.           freefilenodes(start);
  836.           usage();
  837.         }
  838.         break;
  839.  
  840.       /* destination is a directory */
  841.       case 1:
  842.         freefib(endfib);
  843.         break;
  844.  
  845.       /* destination doesn't exist */
  846.       case 2:
  847.         if ( args == 2 && !isdir(start->name,&startfib) ) {
  848.  
  849.           /*
  850.            * move file specified in start->name to a new
  851.            * file in endnode->name
  852.            */
  853.           result = mv2f(start->name,startfib,endnode->name,NULL);
  854.  
  855.           if ( result == 2 && mvflag ) {
  856.             rm(start->name,fflag,iflag);
  857.           }
  858.  
  859.           freefib(endfib);
  860.           freefib(startfib);
  861.           freefilenodes(start);
  862.           exit(0);
  863.         } else {
  864.           if ( args > 2 ) {
  865.             struct FileLock *lock;
  866.             char *buf = newbuf();
  867.  
  868.             freefib(startfib);
  869.             freefib(endfib);
  870.  
  871.             if ( !buf ) {
  872.               freefilenodes(start);
  873.               exit(-1);
  874.             }
  875.  
  876.             if ( iflag ) {
  877.               buf[0] = '\0';
  878.               emit(ofile,commandname);
  879.               emit(ofile,": create directory ");
  880.               emit(ofile,endnode->name);
  881.  
  882.               Read(ifile,buf,BUFSIZE);
  883.  
  884.               if ( buf[0] != 'y' && buf[0] != 'Y' ) {
  885.                 break;
  886.               }
  887.             }
  888.  
  889.             if ( !(lock = CreateDir(endnode->name)) ) {
  890.               if ( !fflag ) {
  891.                 emit(ofile,commandname);
  892.                 emit(ofile,": unable to create directory ");
  893.                 emit(ofile,endnode->name);
  894.                 emit(ofile,"\n");
  895.               }
  896. #             ifdef ARP
  897.               closethings();
  898. #             endif
  899.               freefilenodes(start);
  900.               freebuf(buf);
  901.               exit(-1);
  902.             } else {
  903.               UnLock(lock);
  904.             }
  905.             freebuf(buf);
  906.           }
  907.         }
  908.         break;
  909.  
  910.       case 3:
  911.         if ( !fflag ) {
  912.           emit(ofile,commandname);
  913.           emit(ofile,": could not examine file ");
  914.           emit(ofile,endnode->name);
  915.           emit(ofile,"\n");
  916.         }
  917.  
  918.         freefilenodes(start);
  919.         freefib(endfib);
  920.         exit(3);
  921.         break;
  922.     }
  923.  
  924. # ifdef DEBUG
  925.   printf("Move or copy files to directory %s\n",endnode->name);
  926. # endif
  927.   }
  928.  
  929.   /*
  930.    * For each source argument, move it to the correct directory.
  931.    */
  932.   for ( temp = start; temp; temp = temp->next ) {
  933.  
  934.     Chk_Abort();
  935.  
  936.     if ( (temp != endnode) && (mvflag || cpflag) ) {
  937.       result = mv(temp->name,endnode->name);
  938.  
  939.       switch ( result ) {
  940.  
  941.         /* if there was an error, get out now */
  942.         case -1:
  943. #         ifdef ARP
  944.           closethings();
  945. #         endif
  946.           freefilenodes(start);
  947.           exit(-1);
  948.  
  949.         /* if there was a successful copy, then remove the source */
  950.         case 2:
  951.           if ( !cpflag )
  952.             rm(temp->name,fflag,iflag);
  953.           break;
  954.  
  955.         /*
  956.          * if there was a successful move, then do nothing, 'cause the
  957.          * source is gone already.
  958.          */
  959.         default:
  960.           break;
  961.       }
  962.     } else if ( rmflag ) {
  963.       rm(temp->name,fflag,iflag);
  964.     }
  965.   }
  966.  
  967. # ifdef ARP
  968.   closethings();
  969. # endif
  970.  
  971.   freefilenodes(start);
  972.  
  973.   exit(0);
  974. }
  975.  
  976. int rm_file(file,fflag,iflag)
  977. char *file;
  978. int fflag, iflag;
  979. {
  980.   register int result;
  981.   char *buf = newbuf();
  982.  
  983.   if ( !buf ) {
  984.     return(-1);
  985.   }
  986.  
  987. # ifdef DEBUG
  988.   printf("Deleting file %s\n",file);
  989. # endif
  990.  
  991.   switch ( isdeletable(file) ) {
  992.     case 2:
  993.       if ( !fflag ) {
  994.         emit(ofile,commandname);
  995.         emit(ofile,": could not find file ");
  996.         emit(ofile,file);
  997.         emit(ofile,"\n");
  998.       }
  999.       result = -1;
  1000.       break;
  1001.  
  1002.     case 1:
  1003.       if ( iflag ) {
  1004.         buf[0] = '\0';
  1005.  
  1006.         emit(ofile,commandname);
  1007.         emit(ofile,": remove ");
  1008.         emit(ofile,file);
  1009.         emit(ofile,"? ");
  1010.  
  1011.         Read(ifile,buf,BUFSIZE);
  1012.  
  1013.         if ( buf[0] != 'y' && buf[0] != 'Y' ) {
  1014.           result = -1;
  1015.           break;
  1016.         }
  1017.       }
  1018.  
  1019.       SetProtection(file,0);
  1020.  
  1021.       if ( !DeleteFile(file) ) {
  1022.         if ( !fflag ) {
  1023.           emit(ofile,commandname);
  1024.           emit(ofile,": could not remove ");
  1025.           emit(ofile,file);
  1026.           emit(ofile,"\n");
  1027.         }
  1028.         result = -1;
  1029.       } else {
  1030.         result = 1;
  1031.       }
  1032.       break;
  1033.  
  1034.     case 0:
  1035.       if ( !fflag ) {
  1036.         buf[0] = '\0';
  1037.  
  1038.         emit(ofile,commandname);
  1039.         emit(ofile,": overide delete protection for file ");
  1040.         emit(ofile,file);
  1041.         emit(ofile,"? ");
  1042.  
  1043.         Read(ifile,buf,BUFSIZE);
  1044.  
  1045.         if ( buf[0] == 'y' || buf[0] == 'Y' ) {
  1046.  
  1047.           SetProtection(file,0);
  1048.  
  1049.           if ( !DeleteFile(file) ) {
  1050.             if ( !fflag ) {
  1051.               emit(ofile,commandname);
  1052.               emit(ofile,": could not remove ");
  1053.               emit(ofile,file);
  1054.               emit(ofile,"\n");
  1055.             }
  1056.             result = -1;
  1057.           } else {
  1058.             result = 1;
  1059.           }
  1060.         } else {
  1061.           result = -1;
  1062.         }
  1063.       } else {
  1064.  
  1065.         SetProtection(file,0);
  1066.  
  1067.         if ( !DeleteFile(file) ) {
  1068.           if ( !fflag ) {
  1069.             emit(ofile,commandname);
  1070.             emit(ofile,": could not remove ");
  1071.             emit(ofile,file);
  1072.             emit(ofile,"\n");
  1073.           }
  1074.           result = -1;
  1075.         } else {
  1076.           result = 1;
  1077.         }
  1078.       }
  1079.       break;
  1080.   }
  1081.  
  1082.   freebuf(buf);
  1083.   return(result);
  1084. }
  1085.  
  1086.  
  1087. /* recursively remove a directory or a remove a file */
  1088. int rm_dir(name,fflag,iflag)
  1089. char *name;
  1090. int fflag, iflag;
  1091. {
  1092.    register struct FileLock *lock, *cwd;
  1093.    register struct FileInfoBlock *fib;
  1094.    register char *buf;
  1095.    register int result = 1;
  1096.  
  1097. # ifdef DEBUG
  1098.   printf("Recursively deleting directory %s\n",name);
  1099. # endif
  1100.  
  1101.    buf = newbuf();
  1102.    fib = (struct FileInfoBlock *)AllocMem(FIBSIZE,MEMF_CLEAR);
  1103.  
  1104.    if (lock = Lock(name, ACCESS_READ)) {
  1105.  
  1106.       cwd = CurrentDir(lock);
  1107.  
  1108.       if (Examine(lock, fib)) {
  1109.  
  1110.          buf[0] = '\0';
  1111.  
  1112.          while (result && ExNext(lock, fib)) {
  1113.  
  1114.             if ( fib->fib_DirEntryType > 0 )
  1115.                result = rm_dir(fib->fib_FileName,fflag,iflag);
  1116.  
  1117.             if (buf[0]) {
  1118.                rm_file(buf,fflag,iflag);
  1119.             }
  1120.  
  1121.             strcpy(buf, fib->fib_FileName);
  1122.          }
  1123.  
  1124.          if ( buf[0] ) {
  1125.             rm_file(buf,fflag,iflag);
  1126.          }
  1127.       }
  1128.  
  1129.       UnLock(CurrentDir(cwd));
  1130.  
  1131.    } else {
  1132.      if ( !fflag ) {
  1133.         emit(ofile,commandname);
  1134.         emit(ofile,": could not get a lock on ");
  1135.         emit(ofile,name);
  1136.         emit(ofile,"\n");
  1137.       }
  1138.       result = -1;
  1139.    }
  1140.  
  1141.    FreeMem(fib, FIBSIZE);
  1142.    freebuf(buf);
  1143.  
  1144.    return(result);
  1145. }
  1146.  
  1147. rm(name,fflag,iflag)
  1148. char *name;
  1149. int fflag,iflag;
  1150. {
  1151.   int result;
  1152.   struct FileInfoBlock *fib;
  1153.  
  1154.   switch ( isdir(name,&fib) ) {
  1155.     case 0:
  1156.       result = rm_file(name,fflag,iflag);
  1157.       break;
  1158.  
  1159.     case 1:
  1160.       if ( rflag ) {
  1161.         /* recursively delete the directory */
  1162.         result = rm_dir(name,fflag,iflag);
  1163.         if ( result ) {
  1164.           rm_file(name,fflag,iflag);
  1165.         }
  1166.       } else if ( dflag ) {
  1167.  
  1168.         /* only deletes directory if it is empty, as in AmigaDOS Delete */
  1169.         result = rm_file(name,fflag,iflag);
  1170.  
  1171.       } else {
  1172.         if ( !fflag ) {
  1173.           emit(ofile,commandname);
  1174.           emit(ofile,": ");
  1175.           emit(ofile,name);
  1176.           emit(ofile," is a directory (not removed)\n");
  1177.         }
  1178.         result = -1;
  1179.       }
  1180.       break;
  1181.  
  1182.     case 2:
  1183.       if ( !fflag ) {
  1184.         emit(ofile,commandname);
  1185.         emit(ofile,": could not access file ");
  1186.         emit(ofile,name);
  1187.         emit(ofile,"\n");
  1188.       }
  1189.       break;
  1190.  
  1191.  
  1192.     case 3:
  1193.       if ( !fflag ) {
  1194.         emit(ofile,commandname);
  1195.         emit(ofile,": could not examine file ");
  1196.         emit(ofile,name);
  1197.         emit(ofile,"\n");
  1198.       }
  1199.       break;
  1200.   }
  1201.  
  1202.   if ( fib )
  1203.     freefib(fib);
  1204.  
  1205.   return(result);
  1206. }
  1207.  
  1208.  
  1209. /* mv a file or directory _to_a_directory_ */
  1210. int mv(src,dst)
  1211. char *src, *dst;
  1212. {
  1213.   register int result = 0;
  1214.   struct FileInfoBlock *srcfib;
  1215.  
  1216.   switch ( isdir(src,&srcfib) ) {
  1217.  
  1218.     /* source is a file */
  1219.     case 0:
  1220.       result = mvfile(src,srcfib,dst);
  1221.       break;
  1222.  
  1223.     /* source is a directory */
  1224.     case 1:
  1225.       result = mvdir(src,srcfib,dst);
  1226.       break;
  1227.  
  1228.     /* no access to source */
  1229.     case 2:
  1230.       if ( !fflag ) {
  1231.         emit(ofile,commandname);
  1232.         emit(ofile,": could not access file ");
  1233.         emit(ofile,src);
  1234.         emit(ofile,"\n");
  1235.       }
  1236.       result = 0;
  1237.       break;
  1238.  
  1239.     /* not able to examine source */
  1240.     case 3:
  1241.       if ( !fflag ) {
  1242.         emit(ofile,commandname);
  1243.         emit(ofile,": could not examine file ");
  1244.         emit(ofile,src);
  1245.         emit(ofile,"\n");
  1246.       }
  1247.       result = 0;
  1248.       break;
  1249.   }
  1250.  
  1251.   freefib(srcfib);
  1252.   return(result);
  1253. }
  1254.  
  1255. /* mv to a destination dir _from_ a directory source */
  1256. int mvdir(src,srcfib,dst)
  1257. char *src, *dst;
  1258. struct FileInfoBlock *srcfib;
  1259. {
  1260.   register int result = 1, temp, onsame;
  1261.   struct FileInfoBlock *dstfib;
  1262.  
  1263.   if ( (onsame = samedev(src,dst)) == -1 )
  1264.     return(0);
  1265.  
  1266.   temp = isdir(dst,&dstfib);
  1267.  
  1268.   /* if they are on the same device, treat the src dir as a file */
  1269.   if ( onsame && mvflag ) {
  1270.  
  1271.     /* if the destination dir doesn't exist, then move onto it... */
  1272.     if ( temp == 2 ) {
  1273.  
  1274.       result = mv2f(src,srcfib,dst,NULL);
  1275.     } else {
  1276.  
  1277.       /* ...else move into it */
  1278.       result = mv2d(src,srcfib,dst);
  1279.     }
  1280.  
  1281.   } else if ( mvflag || (cpflag && rflag) ) {
  1282.  
  1283.     /* ugh. We have to copy the source dir to the destination dir */
  1284.  
  1285.     register int success, len;
  1286.     register char c;
  1287.     register struct FileLock *oldlock, *newlock, *dstlock;
  1288.     char *buf = newbuf();
  1289.     char *dstbuf = newbuf();
  1290.     register struct FileInfoBlock *fib = newfib();
  1291.  
  1292.     if ( !fib || !buf || !dstbuf ) {
  1293.       result = -1;
  1294.     } else {
  1295.  
  1296.       dstbuf[0] = '\0';
  1297.  
  1298.       strcat(dstbuf,dst);
  1299.  
  1300.       if ( temp != 2 ) {
  1301.         /*
  1302.          * build the name of the destination from the directory name and
  1303.          * later, the file name
  1304.          */
  1305.  
  1306.         len = strlen(dstbuf);
  1307.  
  1308.         /*
  1309.          * only append a slash if the file name is not the current directory,
  1310.          * (ie. "") the last character is not null, and the last character
  1311.          * is neither of ':' or '/'. This part is so much easier under Unix
  1312.          * path naming conventions, but hey, Amigoids gotta be different!
  1313.          */
  1314.         if ( len && (c = dstbuf[len - 1] ) && c != ':' && c != '/' )
  1315.           strcat(dstbuf,"/");
  1316.  
  1317.         /*
  1318.          * add only the file name onto the destination directory to
  1319.          * build the name of the file we want to move to
  1320.          */
  1321.         strcat(dstbuf,basename(src));
  1322.       }
  1323.  
  1324.       /* see if the directory exists */
  1325.       if ( !(dstlock = Lock(dstbuf,ACCESS_READ)) ) {
  1326.         struct DateStamp ds;
  1327.  
  1328.         /* if no lock, try creating it */
  1329.  
  1330.         if ( iflag ) {
  1331.           buf[0] = '\0';
  1332.  
  1333.           emit(ofile,commandname);
  1334.           emit(ofile,": create directory ");
  1335.           emit(ofile,dstbuf);
  1336.           emit(ofile,"? ");
  1337.  
  1338.           Read(ifile,buf,BUFSIZE);
  1339.  
  1340.           if ( buf[0] != 'y' && buf[0] != 'Y' ) {
  1341.             freefib(fib);
  1342.             freefib(dstfib);
  1343.  
  1344.             return(0);
  1345.           }
  1346.         }
  1347.  
  1348.         if ( !(dstlock = CreateDir(dstbuf)) ) {
  1349.           if ( !fflag ) {
  1350.             emit(ofile,commandname);
  1351.             emit(ofile,": unable to create directory ");
  1352.             emit(ofile,dstbuf);
  1353.             emit(ofile,"\n");
  1354.           }
  1355.           return(0);
  1356.         }
  1357. #       ifdef DEBUG
  1358.         printf("Created directory %s\n",dstbuf);
  1359. #       endif
  1360.  
  1361.         setdate(&srcfib->fib_Date,dstbuf);
  1362.  
  1363.       }
  1364.  
  1365.       UnLock(dstlock);
  1366.  
  1367.       /*
  1368.        * get a lock on the source directory, since we have to copy it
  1369.        * recursively
  1370.        */
  1371.       newlock = Lock(src,ACCESS_READ);
  1372.  
  1373.       /* Take a look at the directory */
  1374.       success = Examine(newlock,fib);
  1375.  
  1376.       /*
  1377.        * while the examination of the source directory worked and the
  1378.        * last move worked...
  1379.        */
  1380.       while ( ExNext(newlock,fib) && result > 0 ) {
  1381.  
  1382.         /* build the source file name */
  1383.         buf[0] = '\0';
  1384.  
  1385.         strcat(buf,src);
  1386.  
  1387.         len = strlen(buf);
  1388.  
  1389.         if ( len && (c = buf[len - 1] ) && c != ':' && c != '/' )
  1390.           strcat(buf,"/");
  1391.  
  1392.         strcat(buf,&fib->fib_FileName[0]);
  1393.  
  1394.         result = mv(buf,dstbuf);
  1395.       }
  1396.  
  1397.       UnLock(newlock);
  1398.     }
  1399.  
  1400.     freefib(fib);
  1401.     freebuf(buf);
  1402.     freebuf(dstbuf);
  1403.  
  1404.   } else {
  1405.     if ( !fflag ) {
  1406.       emit(ofile,commandname);
  1407.       emit(ofile,": ");
  1408.       emit(ofile,src);
  1409.       emit(ofile," is a directory (not copied)\n");
  1410.     }
  1411.   }
  1412.  
  1413.   freefib(dstfib);
  1414.  
  1415.   return(result);
  1416. }
  1417.  
  1418. /* mv to a destination file or directory _from_ a file */
  1419. int mvfile(src,srcfib,dst)
  1420. char *src, *dst;
  1421. struct FileInfoBlock *srcfib;
  1422. {
  1423.   register int result = 0;
  1424.   struct FileInfoBlock *dstfib;
  1425.   char *buf = newbuf();
  1426.  
  1427.   if ( !buf ) {
  1428.     return(-1);
  1429.   }
  1430.  
  1431.   switch ( isdir(dst,&dstfib) ) {
  1432.  
  1433.     /* destination is a file */
  1434.     case 0:
  1435.       result = mv2f(src,srcfib,dst,dstfib);
  1436.       break;
  1437.  
  1438.     /* destination is a directory */
  1439.     case 1:
  1440.       result = mv2d(src,srcfib,dst);
  1441.       break;
  1442.  
  1443.     case 2:
  1444.       if ( iflag ) {
  1445.         buf[0] = '\0';
  1446.  
  1447.         emit(ofile,commandname);
  1448.         emit(ofile,": create directory ");
  1449.         emit(ofile,dst);
  1450.         emit(ofile,"? ");
  1451.  
  1452.         Read(ifile,buf,BUFSIZE);
  1453.  
  1454.         if ( buf[0] != 'y' && buf[0] != 'Y' ) {
  1455.           result = 0;
  1456.           break;
  1457.         }
  1458.       }
  1459. #     ifdef DEBUG
  1460.       printf("Creating dir %s\n",dst);
  1461. #     endif
  1462.  
  1463.       lock = CreateDir(dst);
  1464.  
  1465.       if ( !lock ) {
  1466.         if ( !fflag ) {
  1467.           emit(ofile,commandname);
  1468.           emit(ofile,": could not create destination directory ");
  1469.           emit(ofile,dst);
  1470.           emit(ofile,"\n");
  1471.         }
  1472.         result = 0;
  1473.       } else {
  1474.  
  1475.         UnLock(lock);
  1476.         result = mv2d(src,srcfib,dst);
  1477.       }
  1478.  
  1479.       break;
  1480.  
  1481.     case 3:
  1482.       if ( !fflag ) {
  1483.         emit(ofile,commandname);
  1484.         emit(ofile,": could not examine directory ");
  1485.         emit(ofile,dst);
  1486.         emit(ofile,"\n");
  1487.       }
  1488.       result = 0;
  1489.       break;
  1490.   }
  1491.  
  1492.   freefib(dstfib);
  1493.   freebuf(buf);
  1494.   return(result);
  1495. }
  1496.  
  1497. /* mv a file _to_ a directory dst */
  1498. int mv2d(src,srcfib,dst)
  1499. char *src, *dst;
  1500. struct FileInfoBlock *srcfib;
  1501. {
  1502.   char *buf = newbuf();
  1503.   register char c;
  1504.   register int result = 0;
  1505.   register int len = strlen(dst);
  1506.   struct FileInfoBlock *dstfib;
  1507.  
  1508.   if ( !buf ) {
  1509.     return(-1);
  1510.   }
  1511.  
  1512.   buf[0] = '\0';
  1513.  
  1514.   /* build the file name in the destination directory */
  1515.   strcat(buf,dst);
  1516.  
  1517.   if ( len && (c = buf[len - 1] ) && c != ':' && c != '/' )
  1518.     strcat(buf,"/");
  1519.  
  1520.   strcat(buf,basename(src));
  1521.  
  1522.   switch ( isdir(buf,&dstfib) ) {
  1523.  
  1524.     case 0:
  1525.       result = mv2f(src,srcfib,buf,dstfib);
  1526.       break;
  1527.  
  1528.     case 1:
  1529.       if ( !fflag ) {
  1530.         emit(ofile,commandname);
  1531.         emit(ofile,": could not move file ");
  1532.         emit(ofile,src);
  1533.         emit(ofile," onto directory ");
  1534.         emit(ofile,buf);
  1535.         emit(ofile,"\n");
  1536.       }
  1537.       result = 0;
  1538.       break;
  1539.  
  1540.     case 2:
  1541.       result = mv2f(src,srcfib,buf,NULL);
  1542.       break;
  1543.  
  1544.     case 3:
  1545.       if ( !fflag ) {
  1546.         emit(ofile,commandname);
  1547.         emit(ofile,": something is awry with file ");
  1548.         emit(ofile,buf);
  1549.         emit(ofile,"\n");
  1550.       }
  1551.       result = 0;
  1552.       break;
  1553.   }
  1554.  
  1555.   freefib(dstfib);
  1556.   freebuf(buf);
  1557.   return(result);
  1558. }
  1559.  
  1560. /* mv a file _to_ a file */
  1561. int mv2f(src,srcfib,dst,dstfib)
  1562. char *src, *dst;
  1563. struct FileInfoBlock *srcfib, *dstfib;
  1564. {
  1565.   register int result = 0, cleanup = 0;
  1566.   char *inputbuf;
  1567.   register int onsame;
  1568.  
  1569.   /* are they on the same volume? */
  1570.   if ( (onsame = samedev(src,dst)) == -1) {
  1571.     freebuf(inputbuf);
  1572.     return(0);
  1573.   }
  1574.  
  1575.   if ( !(inputbuf = newbuf()) ) {
  1576.     return(-1);
  1577.   }
  1578.  
  1579.   if ( dstfib ) {
  1580.     if ( onsame && srcfib->fib_DiskKey == dstfib->fib_DiskKey ) {
  1581.  
  1582.       if ( !mvflag ) {
  1583.         if ( !fflag ) {
  1584.           emit(ofile,commandname);
  1585.           emit(ofile,": cannot copy ");
  1586.           emit(ofile,src);
  1587.           emit(ofile," to itself!\n");
  1588.         }
  1589.         freebuf(inputbuf);
  1590.         return(1);
  1591.       }
  1592.  
  1593.     } else {
  1594.  
  1595.       if ( iflag ) {
  1596.         inputbuf[0] = '\0';
  1597.  
  1598.         emit(ofile,commandname);
  1599.         emit(ofile,": overwrite ");
  1600.         emit(ofile,dst);
  1601.         emit(ofile,"? ");
  1602.  
  1603.         Read(ifile,inputbuf,BUFSIZE);
  1604.  
  1605.         if ( inputbuf[0] != 'y' && inputbuf[0] != 'Y' ) {
  1606.           freebuf(inputbuf);
  1607.           return(1);
  1608.         }
  1609.  
  1610.         /* if remove unsuccessful, return an error */
  1611.         if ( rm_file(dst,1,0) == -1 ) {
  1612.           freebuf(inputbuf);
  1613.           return(0);
  1614.         }
  1615.  
  1616.       } else {
  1617.  
  1618.         /* if remove unsuccessful, return an error */
  1619.         if ( rm_file(dst,fflag,0) == -1 ) {
  1620.           freebuf(inputbuf);
  1621.           return(0);
  1622.         }
  1623.  
  1624.       }
  1625.     }
  1626.   }
  1627.  
  1628.   result = (onsame && mvflag) ? move(src,dst) : cp(src,srcfib,dst);
  1629.  
  1630.   freebuf(inputbuf);
  1631.  
  1632.   return(result);
  1633. }
  1634.  
  1635. /* copy a source file to a destination file */
  1636. int cp(src,srcfib,dst)
  1637. char *src, *dst;
  1638. struct FileInfoBlock *srcfib;
  1639. {
  1640.   register int num;
  1641.   register long size;
  1642.   register char *buf;
  1643.   struct FileHandle *srchandle, *dsthandle;
  1644.  
  1645. # ifdef DEBUG
  1646.   printf("copy file %s to %s\n",src,dst);
  1647. # endif
  1648.  
  1649.   size = mem() - 4;
  1650.  
  1651.   if ( size < 128 ) {
  1652.     if ( !fflag ) {
  1653.       emit(ofile,commandname);
  1654.       emit(ofile,": Out of memory!\n");
  1655.     }
  1656.     return(-1);
  1657.   }
  1658.  
  1659.   /*
  1660.    * allocate a maximum of "size" continous bytes, else source file
  1661.    * size worth of bytes. This allows one read and one write if there
  1662.    * is enough memory for it. The 8 is added in case there is a
  1663.    * zero size file we want to copy and we still want to allocate
  1664.    * a buffer anyways.
  1665.    */
  1666.   size = ( srcfib->fib_Size + 8 > size ) ? size : srcfib->fib_Size + 8;
  1667.  
  1668. # ifdef DEBUG
  1669.   printf("Allocating %d bytes for the copy\n",size);
  1670. # endif
  1671.  
  1672.   if ( !(buf = AllocMem(size,MEMF_CLEAR|MEMF_PUBLIC)) ) {
  1673.     /* didn't work, try again with a smaller size */
  1674.     size = size / 4;
  1675.  
  1676.     if ( !(buf = AllocMem(size,MEMF_CLEAR|MEMF_PUBLIC)) ) {
  1677.       if ( !fflag ) {
  1678.         emit(ofile,commandname);
  1679.         emit(ofile,": Out of memory!\n");
  1680.       }
  1681.       return(-1);
  1682.     }
  1683.   }
  1684.  
  1685.   /* if we can't open the file, return an error */
  1686.   if ( !(dsthandle = Open(dst,MODE_NEWFILE)) ) {
  1687.     if ( !fflag ) {
  1688.       emit(ofile,commandname);
  1689.       emit(ofile,": cannot Open file ");
  1690.       emit(ofile,dst);
  1691.       emit(ofile,"\n");
  1692.     }
  1693.     FreeMem(buf,size);
  1694.  
  1695.     /* returning 0 indicates an error to the above routines */
  1696.     return(0);
  1697.   }
  1698.  
  1699.   if ( !(srchandle = Open(src,MODE_OLDFILE)) ) {
  1700.     if ( !fflag ) {
  1701.       emit(ofile,commandname);
  1702.       emit(ofile,": cannot Open file ");
  1703.       emit(ofile,src);
  1704.       emit(ofile,"\n");
  1705.     }
  1706.     Close(dsthandle);
  1707.     FreeMem(buf,size);
  1708.     return(0);
  1709.   }
  1710.  
  1711.   /* copy bytes back and forth. Read returns -1 for a read error */
  1712.   while ( (num = Read(srchandle,buf,size)) > 0 ) {
  1713.     if ( Write(dsthandle,buf,num) == -1 ) {
  1714.       if ( !fflag ) {
  1715.         emit(ofile,commandname);
  1716.         emit(ofile,": error writing to file ");
  1717.         emit(ofile,dst);
  1718.         emit(ofile,". Disk may be full.\n");
  1719.       }
  1720.       Close(srchandle);
  1721.       Close(dsthandle);
  1722.       FreeMem(buf,size);
  1723.       return(-1);
  1724.     }
  1725.   }
  1726.  
  1727.   Close(srchandle);
  1728.   Close(dsthandle);
  1729.  
  1730.   if ( num == -1 ) {
  1731.     if ( !fflag ) {
  1732.       emit(ofile,commandname);
  1733.       emit(ofile,": error reading from file ");
  1734.       emit(ofile,src);
  1735.       emit(ofile,"\n");
  1736.     }
  1737.     FreeMem(buf,size);
  1738.     return(0);
  1739.   }
  1740.  
  1741.   if ( nflag ) {
  1742.     /*
  1743.      * copy the protection bits, the comment and the datestamp to the
  1744.      * new file if the n flag is set (ie. -n was NOT specified in the
  1745.      * commandline)
  1746.      */
  1747.     SetProtection(dst,srcfib->fib_Protection);
  1748.  
  1749.     SetComment(dst,srcfib->fib_Comment);
  1750.  
  1751.     setdate(&srcfib->fib_Date,dst);
  1752.  
  1753.     FreeMem(buf,size);
  1754.   }
  1755.  
  1756.   /* return 2 for successful copy (not 1, because 1 is a move) */
  1757.   return(2);
  1758. }
  1759.  
  1760. /* rename a source file to a destination file */
  1761. int move(src,dst)
  1762. char *src, *dst;
  1763. {
  1764.   register int foo;
  1765.  
  1766. # ifdef DEBUG
  1767.   printf("move file %s to %s\n",src,dst);
  1768. # endif
  1769.  
  1770.   /* return 1 for successful move */
  1771.   foo =  Rename(src,dst) ? 1 : 0;
  1772.  
  1773.   if ( !foo && !fflag ) {
  1774.     emit(ofile,commandname);
  1775.     emit(ofile,": could not move file ");
  1776.     emit(ofile,src);
  1777.     emit(ofile," to ");
  1778.     emit(ofile,dst);
  1779.     emit(ofile,"\n");
  1780.   }
  1781.  
  1782.   return(foo);
  1783. }
  1784.  
  1785. int setdate(date,name)
  1786. struct DateStamp *date;
  1787. char *name;
  1788. {
  1789.   register UBYTE *ptr;
  1790.   struct MsgPort *task;
  1791.   register struct FileLock *lock, *parent;
  1792.   register struct FileInfoBlock *fib;
  1793.   int stat, result, dos_packet();
  1794.  
  1795.   if ( !(task = DeviceProc(name)) ) {
  1796.     return(0);
  1797.   }
  1798.  
  1799.   if ( !(lock = Lock(name,ACCESS_READ)) ) {
  1800.     return(0);
  1801.   }
  1802.  
  1803.   fib = newfib();
  1804.  
  1805.   /*
  1806.    * thanks to Matt Dillon for this routine. I really don't know how
  1807.    * it does what it does, but it works, so no comments here.
  1808.    */
  1809.  
  1810.   /*
  1811.    * Well, I mean other than these comments...
  1812.    */
  1813.  
  1814.   /*
  1815.    * Oh, forget it.
  1816.    */
  1817.   if ( fib ) {
  1818.     if ( Examine(lock,fib) ) {
  1819.  
  1820.       parent = ParentDir(lock);
  1821.  
  1822.       UnLock(lock);
  1823.  
  1824.       ptr = (UBYTE *) AllocMem(256L,MEMF_CLEAR|MEMF_PUBLIC);
  1825.  
  1826.       strcpy((ptr + 1),fib->fib_FileName);
  1827.  
  1828.       *ptr = (UBYTE) strlen(fib->fib_FileName);
  1829.  
  1830.       result = dos_packet(task,34L,NULL,parent,(ULONG)&ptr[0] >> 2L,date);
  1831.  
  1832.       FreeMem(ptr,256L);
  1833.  
  1834.       UnLock(parent);
  1835.     }
  1836.  
  1837.     freefib(fib);
  1838.  
  1839.   } else {
  1840.     UnLock(lock);
  1841.   }
  1842. }
  1843.  
  1844. /* is a file delete protected? */
  1845. int isdeletable(file)
  1846. char *file;
  1847. {
  1848.   register struct FileLock *lock;
  1849.   register struct FileInfoBlock *fib;
  1850.   register int result = 0;
  1851.  
  1852.   if ( !(lock = Lock(file,ACCESS_READ)) ) {
  1853.     return(0);
  1854.   }
  1855.  
  1856.   /* allocate a word aligned memory block to hold our info */
  1857.   fib = newfib();
  1858.  
  1859.   if ( fib ) {
  1860.     if ( Examine(lock,fib) ) {
  1861.  
  1862.       result = fib->fib_Protection;
  1863.       freefib(fib);
  1864.  
  1865.     } else {
  1866.  
  1867.       freefib(fib);
  1868.       return(2);
  1869.     }
  1870.  
  1871.   }
  1872.  
  1873.  
  1874.   UnLock(lock);
  1875.  
  1876.   return( !(result & FIBF_DELETE) );
  1877. }
  1878.  
  1879.  
  1880.